<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Canvas Filter Example</title>
    <style>
        body {
            font-family: Arial, sans-serif;
            display: flex;
            flex-direction: column;
            align-items: center;
            margin: 20px;
        }
        #controls {
            margin: 20px 0;
        }
        #canvas {
            border: 1px solid black;
        }
    </style>
</head>
<body>
    <h1>Canvas Filter Example</h1>
    <input type="file" id="fileInput" accept="image/*">
    <div id="controls">
        <label for="hueRange">Hue: </label>
        <input type="range" id="hueRange" min="0" max="360" value="0">
        <span id="hueValue">0</span><br>
        <label for="saturationRange">Saturation: </label>
        <input type="range" id="saturationRange" min="0" max="200" value="100">
        <span id="saturationValue">100%</span><br>
        <label for="filterSelect">Filter: </label>
        <select id="filterSelect">
            <option value="none">None</option>
            <option value="lens">Convex Lens</option>
            <option value="sketch">Sketch</option>
            <option value="grayscale">Grayscale</option>
            <option value="pencil">Pencil Sketch</option>
        </select>
    </div>
    <canvas id="canvas" width="500" height="500"></canvas>

    <script>
        const fileInput = document.getElementById('fileInput');
        const canvas = document.getElementById('canvas');
        const ctx = canvas.getContext('2d');
        const hueRange = document.getElementById('hueRange');
        const hueValue = document.getElementById('hueValue');
        const saturationRange = document.getElementById('saturationRange');
        const saturationValue = document.getElementById('saturationValue');
        const filterSelect = document.getElementById('filterSelect');
        let img = new Image();

        fileInput.addEventListener('change', (e) => {
            const file = e.target.files[0];
            if (file) {
                const reader = new FileReader();
                reader.onload = (event) => {
                    img.onload = () => {
                        drawImageWithFilter();
                    };
                    img.src = event.target.result;
                };
                reader.readAsDataURL(file);
            }
        });

        hueRange.addEventListener('input', (e) => {
            hueValue.textContent = e.target.value;
            drawImageWithFilter();
        });

        saturationRange.addEventListener('input', (e) => {
            saturationValue.textContent = e.target.value + '%';
            drawImageWithFilter();
        });

        filterSelect.addEventListener('change', drawImageWithFilter);

        function drawImageWithFilter() {
            const hue = hueRange.value;
            const saturation = saturationRange.value + '%';
            ctx.clearRect(0, 0, canvas.width, canvas.height);
            ctx.filter = `hue-rotate(${hue}deg) saturate(${saturation})`;
            ctx.drawImage(img, 0, 0, canvas.width, canvas.height);

            const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
            const data = imageData.data;
            const filter = filterSelect.value;

            if (filter === 'lens') {
                applyLensFilter(imageData);
            } else if (filter === 'sketch') {
                applySketchFilter(imageData);
            } else if (filter === 'grayscale') {
                applyGrayscaleFilter(imageData);
            } else if (filter === 'pencil') {
                applyPencilSketchFilter(imageData);
            }

            ctx.putImageData(imageData, 0, 0);
        }

        function applyLensFilter(imageData) {
            // Convex lens filter algorithm
            const data = imageData.data;
            const width = imageData.width;
            const height = imageData.height;
            const centerX = width / 2;
            const centerY = height / 2;
            const maxDist = Math.sqrt(centerX * centerX + centerY * centerY);
            const factor = 0.5; // Adjust for lens effect strength

            for (let y = 0; y < height; y++) {
                for (let x = 0; x < width; x++) {
                    const dx = x - centerX;
                    const dy = y - centerY;
                    const dist = Math.sqrt(dx * dx + dy * dy);
                    const t = dist / maxDist;

                    const nx = centerX + dx * (1 + factor * t * t);
                    const ny = centerY + dy * (1 + factor * t * t);

                    if (nx >= 0 && nx < width && ny >= 0 && ny < height) {
                        const srcIndex = (Math.floor(ny) * width + Math.floor(nx)) * 4;
                        const destIndex = (y * width + x) * 4;

                        data[destIndex] = data[srcIndex];
                        data[destIndex + 1] = data[srcIndex + 1];
                        data[destIndex + 2] = data[srcIndex + 2];
                    }
                }
            }
        }

        function applySketchFilter(imageData) {
            // Sketch filter algorithm
            const data = imageData.data;
            const width = imageData.width;
            const height = imageData.height;

            for (let i = 0; i < data.length; i += 4) {
                const avg = (data[i] + data[i + 1] + data[i + 2]) / 3;
                data[i] = avg;
                data[i + 1] = avg;
                data[i + 2] = avg;
            }

            for (let y = 0; y < height; y++) {
                for (let x = 0; x < width; x++) {
                    const index = (y * width + x) * 4;
                    const nextIndex = ((y + 1) * width + x) * 4;
                    if (y < height - 1) {
                        data[index] = Math.abs(data[index] - data[nextIndex]) * 3;
                        data[index + 1] = Math.abs(data[index + 1] - data[nextIndex + 1]) * 3;
                        data[index + 2] = Math.abs(data[index + 2] - data[nextIndex + 2]) * 3;
                    }
                }
            }
        }

        function applyGrayscaleFilter(imageData) {
            // Grayscale filter algorithm
            const data = imageData.data;
            for (let i = 0; i < data.length; i += 4) {
                const avg = (data[i] + data[i + 1] + data[i + 2]) / 3;
                data[i] = avg;
                data[i + 1] = avg;
                data[i + 2] = avg;
            }
        }

        function applyPencilSketchFilter(imageData) {
            // Pencil sketch filter algorithm
            applyGrayscaleFilter(imageData);

            const data = imageData.data;
            const width = imageData.width;
            const height = imageData.height;

            for (let y = 0; y < height; y++) {
                for (let x = 0; x < width; x++) {
                    const index = (y * width + x) * 4;
                    const nextIndex = ((y + 1) * width + x + 1) * 4;
                    if (x < width - 1 && y < height - 1) {
                        data[index] = Math.abs(data[index] - data[nextIndex]) * 2;
                        data[index + 1] = Math.abs(data[index + 1] - data[nextIndex + 1]) * 2;
                        data[index + 2] = Math.abs(data[index + 2] - data[nextIndex + 2]) * 2;
                    }
                }
            }
        }
    </script>
</body>
</html>
